﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Data;
using System.Windows.Documents;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Imaging;
using System.Windows.Navigation;
using System.Windows.Shapes;
using DiscoveryLogic.Analytics.BusinessLogic.Clusters;
using DiscoveryLogic.Analytics.BusinessLogic.Rules;
using DiscoveryLogic.Analytics.DataObjects;
using DiscoveryLogic.Analytics.DataObjects.Networks;
using DiscoveryLogic.Analytics.DataObjects.Rules;
using DiscoveryLogic.Common.Utilities;

namespace DiscoveryLogic.Analytics.Modules.Clusters
{
    /// <summary>
    /// Interaction logic for ClusterNetworkEditor.xaml
    /// </summary>
    public partial class ClusterNetworkEditor : UserControl
    {
        public delegate void OnNetworkClustered(Network network);
        public event OnNetworkClustered NetworkClustered;

        public delegate void OnStatusChanged(string msg, int pct);
        public event OnStatusChanged StatusChanged;

        private Dictionary<string, EntityClusterRule> _ClusterRules;
        private string _NetworkName;
        private BackgroundWorker _BgWorker;

        public ClusterNetworkEditor(string networkName)
        {
            InitializeComponent();
            this._NetworkName = networkName;
        }

        private void UserControl_Loaded(object sender, RoutedEventArgs e)
        {
            this.cboEntityType.Items.Clear();
            List<EntityType> availableEntityTypes=new List<EntityType>();
            Network network = Network.Read(this._NetworkName);
            foreach(EntityBase entity in network.Records)
            {
                if(!availableEntityTypes.Contains(entity.EntityType))
                    availableEntityTypes.Add(entity.EntityType);
            }
            foreach (EntityType entityType in availableEntityTypes)
                this.cboEntityType.Items.Add(entityType.ToString());
            this.cboClusterRule.Items.Clear();
            this._ClusterRules=new Dictionary<string, EntityClusterRule>();
            List<RuleBase> clusterRules = RuleManager.GetRulesByType(RuleType.Cluster, EntityIcons.ClusterRuleIcon);
            if(clusterRules !=null && clusterRules.Count>0)
            {
                foreach(RuleBase rule in clusterRules)
                {
                    this._ClusterRules.Add(rule.RuleName, rule as EntityClusterRule);
                    this.cboClusterRule.Items.Add(rule.RuleName);
                }
            }
        }

        private void cboEntityType_SelectionChanged(object sender, SelectionChangedEventArgs e)
        {
            if(this.cboEntityType.SelectedIndex>=0)
            {
                EntityType entityType =
                    (EntityType) Enum.Parse(typeof (EntityType), this.cboEntityType.SelectedItem.ToString());
                if(this.cboClusterRule.Items.Count>0)
                {
                    for(int i=0;i<this.cboClusterRule.Items.Count;i++)
                    {
                        EntityClusterRule clusterRule = this._ClusterRules[this.cboClusterRule.Items[i].ToString()];
                        if(clusterRule.SrcEntityType==entityType)
                        {
                            this.cboClusterRule.SelectedIndex = i;
                            break;
                        }
                    }
                }
            }
        }

        private void btnCancel_Click(object sender, RoutedEventArgs e)
        {
            if (this.Parent is Window)
            {
                ((Window)this.Parent).Close();
            }
        }

        private void bgWorker_StatusChanged(object sender, ProgressChangedEventArgs e)
        {
            if (this.StatusChanged != null)
                this.StatusChanged(e.UserState.ToString(), e.ProgressPercentage);
        }

        private void bgWorker_Finished(object sender, RunWorkerCompletedEventArgs e)
        {
            Network network = Network.Read(this._NetworkName);
            
            if (this.NetworkClustered != null)
                this.NetworkClustered(network);
        }

        void bgWorker_DoWork(object sender, DoWorkEventArgs e)
        {
            List<EntityClusterRule> rules = (List<EntityClusterRule>) e.Argument;
            Network network = Network.Read(this._NetworkName);
            this._BgWorker.ReportProgress(5, "Network clustering started...");
            NetworkEntityClusterWorker worker = new NetworkEntityClusterWorker(network, rules);
            worker.ClusterNetworkOnEntity();
            this._BgWorker.ReportProgress(0, "Network clustering finished.");
        }

        private void btnOK2_Click(object sender, RoutedEventArgs e)
        {
            this._BgWorker=new BackgroundWorker();
            this._BgWorker.WorkerReportsProgress = true;
            this._BgWorker.WorkerSupportsCancellation = true;
            this._BgWorker.ProgressChanged += new ProgressChangedEventHandler(bgWorker_StatusChanged);
            this._BgWorker.DoWork += new DoWorkEventHandler(bgWorker_DoWork2);
            this._BgWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgWorker_Finished);
            this._BgWorker.RunWorkerAsync(this.sliderThreshold.Value);

            if (this.Parent is Window)
            {
                ((Window)this.Parent).Close();
            }
        }

        private void bgWorker_DoWork2(object sender, DoWorkEventArgs e)
        {
            double sizeThreshold = (double)e.Argument;
            Network network = Network.Read(this._NetworkName);
            this._BgWorker.ReportProgress(5, "Network clustering started...");
            //NetworkDensityClusterWorker worker = new NetworkDensityClusterWorker(network);
            //worker.ClusterNetworkByMinCutTree((int)sizeThreshold);
            NetworkPathClusterWorker worker = new NetworkPathClusterWorker(network);
            worker.ClusterBasedOnCentrality((int)sizeThreshold);
            this._BgWorker.ReportProgress(0, "Network clustering finished.");
        }

        private void btnOK1_Click(object sender, RoutedEventArgs e)
        {
            if (this.cboClusterRule.SelectedIndex >= 0)
            {
                EntityClusterRule clusterRule = this._ClusterRules[this.cboClusterRule.SelectedItem.ToString()];
                List<EntityClusterRule> rules = new List<EntityClusterRule>();
                rules.Add(clusterRule);
                this._BgWorker = new BackgroundWorker();
                this._BgWorker.WorkerReportsProgress = true;
                this._BgWorker.WorkerSupportsCancellation = true;
                this._BgWorker.ProgressChanged += new ProgressChangedEventHandler(bgWorker_StatusChanged);
                this._BgWorker.DoWork += new DoWorkEventHandler(bgWorker_DoWork);
                this._BgWorker.RunWorkerCompleted += new RunWorkerCompletedEventHandler(bgWorker_Finished);
                this._BgWorker.RunWorkerAsync(rules);


                if (this.Parent is Window)
                {
                    ((Window)this.Parent).Close();
                }
            }
        }

        private void Slider_ValueChanged(object sender, RoutedPropertyChangedEventArgs<double> e)
        {
            if(!this.IsInitialized)
                return;

            this.lblThreshold.Content = Math.Round(this.sliderThreshold.Value, 2).ToString();
        }

        private void btnRemoveEntityClusterRule_Click(object sender, RoutedEventArgs e)
        {

        }
    }
}
